#include <stdio.h>
#include <stdint.h>

int main()
{
    typedef unsigned char BYTE;
    BYTE c = 'z';

    // typedef 可以一次指定多个别名
    typedef int antelope, bagel, mushroom;

    // typedef 可以为指针起别名
    typedef int *intptr;

    int a = 10;
    intptr x = &a;

    // typedef 也可以用来为数组类型起别名
    typedef int five_ints[5];
    five_ints x2 = {11, 22, 33, 44, 55};

    // typedef 为函数起别名的写法如下
    typedef signed char (*fp)(void); // 参考：https://blog.csdn.net/fyyyr/article/details/79251546
    // 上面示例中，类型别名fp是一个指针，代表函数signed char (*)(void)。

    /// 主要好处
    // 1）更好的代码可读性
    typedef char *STRING;
    STRING name;

    // 2）为 struct、union、enum 等命令定义的复杂数据结构创建别名，从而便于引用
    struct treenode
    {
        int data;
        struct treenode *next;
    };

    // 3）typedef 方便以后为变量改类型
    typedef struct treenode *Tree;
    // typedef 方便以后为变量改类型。
    typedef float app_float;
    app_float f1, f2, f3;
    // typedef long double app_float;

    // 4）可移植性
    // 某一个值在不同计算机上的类型，可能是不一样的。

    int i = 100000;
    // 上面代码在32位整数的计算机没有问题，但是在16位整数的计算机就会出错。
    int32_t i2 = 100000;

    // 这些整数类型别名都放在头文件stdint.h，不同架构的计算机只需修改这个头文件即可，而无需修改代码。
    // 因此，typedef有助于提高代码的可移植性，使其能适配不同架构的计算机。

    // 5）简化类型声明
    // C 语言有些类型声明相当复杂，比如下面这个。
    char (*(*func(void))[5])(void);

    // typedef 可以简化复杂的类型声明，使其更容易理解。首先，最外面一层起一个类型别名。
    // typedef char (*Func)(void);
    // Func(*x(void))[5];
    // 这个看起来还是有点复杂，就为里面一层也定义一个别名。

    typedef char (*Func)(void);
    typedef Func Arr[5];
    Arr *func_2(void);

    // 上面代码就比较容易解读了:
    // func_2是一个函数，返回一个指向 Arr 类型的指针。
    // Arr是一个数组，有5个成员，每个成员是Func类型。
    // Func是一个函数指针，指向一个无参数、返回字符值的函数。
    return 0;
}